iT邦幫忙

2021 iThome 鐵人賽

DAY 10
0
Modern Web

整合 Google 服務的燃料——透過 Google Apps Script (GAS) 加速你的工作速度系列 第 10

D10 - 如何用 Google Apps Script 自動化對 Google Drive 的操作?(二)自動列出所有檔案並設定權限

  • 分享至 

  • xImage
  •  

來到了第十天。我們的習慣是先講結論,如果你很急著用,可以直接使用這份 Add-On: Drive Explorer,功能還蠻強大的!自己寫的好處是,如果你想結合其他功能會比較方面。對於想知道怎麼做的人,讓我們開始吧!

今天的目標

讓我們借一下昨天的敘述。現在幾乎每天都會打開 Google Drive,但有時當檔案一多,就會面臨兩個問題——權限設置不清,當一個人加入或離職時,要重複好幾次開開關關。又或是要將不同的線上文件寄信並分享給不同人,抑或是交接時的檔案權限轉移,這些都會需要知道檔案 ID。有沒有一個快速的方式,可以讓我們抓出特定資料夾內的檔案 ID,並用一個表格管理權限呢?

  1. 要怎麼列出 Google Drive 中的檔案 ID 們?
  2. 要怎麼取得 Google Drive 中的檔案們的權限?
  3. 要怎麼設定(刪除與新增)Google Drive 中的檔案們的權限給不同人?

這次的主題我們會分成兩天寫。第一題會在昨天跟大家分享了,今天會針對第二題與第三題。那我們就開始吧!


Q2. 要怎麼取得 Google Drive 中的檔案們的權限?

Step 1 是設定試算表;而 Step 2 則是設定資料夾並讀取檔案,可以參考前一篇文章(D9),今天我們從 Step 3 開始。

Step 3 額外再讀取目前權限

這邊我們介紹讀取權限的幾個功能。 Google 系列的產品基本上有三個角色——編輯者、檢視者、評論者,分別就是可以編輯、可以檢視與可以評論(與檢視)。這邊先不特別談擁有者(Owner)。

那對於「權限操作」,目前比較常見的處理功能就是

編輯者 檢視者 加註者
新增(單人) addEditor() addViewer() addCommenter()
新增(多人) addEditors() addViewers() addCommenters()
讀取 getEditors() getViewers() (沒有特定 API,但可以讀取,待會詳細說明)*
刪除 removeEditor() removeViewer() removeCommenter()

Google 的 API 就是這麼樸實無華、簡單易懂。實在是超高境界。那實際上怎麼用呢,我們來看看,首先要先讀到檔案。這邊先設定三個檔案,分別設定一個編輯者、一個檢視者與一個評論者。

權限狀態
Spread Sheet 1 有一名編輯者
Spread Sheet 2 有一名檢視者
Spread Sheet 3 有一名加註者

稍微改一下前一天 D9 的程式碼,來看每份檔案目前的讀取者與編輯者。

function readFiles(){
  let folder = DriveApp.getFolderById(demo_drive_ID);
  let files = folder.getFiles();
  while (files.hasNext()) {
    let file = files.next();
    let file_name = file.getName();
    let editors = file.getEditors();
    let viewers = file.getViewers();
    for(editor of editors){
      Logger.log('File ' +file_name +' has editor: '+editor.getEmail());
    }
    for(viewer of viewers){
      Logger.log('File ' +file_name +' has viewer: '+viewer.getEmail());
    }
  };
}

跑起來長這樣——

仔細看可以發現,它顯示 Spread Sheet 2 和 Spread Sheet 3 都各有一位檢視者,可是明明我們設定的是一位檢視者和一位加註者,為什麼會這樣?那是因為 在讀取使用者時,加註者會被算入檢視者的一種。那有辦法做出區隔嗎?有的,程式碼如下,藉由 file.getAccess 去看原本檔案中,把原本讀 Viewer 的部分再拆成 Viewer 和 Commenter。

    for(viewer of viewers){
      if(file.getAccess(viewer) == "COMMENT"){
        Logger.log('File ' +file_name +' has commenter: '+viewer.getEmail());
      }else{
        Logger.log('File ' +file_name +' has viewer: '+viewer.getEmail());
      }
    }

而結果跑起來者這樣——

接著,我們來將結果寫入 Google Sheet。

Step 4 寫入 Google Sheet

這邊我們借用 D8 的 writeData 程式碼,這邊就先複習一下其功能,完整的文章可以參考 D8。

function writeData(data){
  let starting_row = 2;
  let starting_col = 1;
  let num_row = data.length;
  let num_col = data[0].length;
  let sheet = SpreadsheetApp.getActiveSheet();
  let range = sheet.getRange(starting_row, 
                             starting_col, num_row, num_col);
  range.setValues(data);
}

也複習執行的結果——

好,那接著就是將我們要的 Data 包裝成 Google Sheet 要的格式(Array in array)。我這邊想要知道,檔案名稱、檔案 ID 、擁有的編輯者、擁有的檢視者與擁有的加註者。

這段是目前最長的程式碼,但跟 Step 3 比起來,就是多加了個「放入檔案」的程序。

  1. 在一開始先放一個 ["File Name","File ID", "Editors","Viewers","Commenters"] 做為預設的 Header(會出現在第一列)
  2. 再來對每個檔案都用一個 file_info ,依序放入 Name 和 ID
  3. 並去讀它的 EditorsViewers
  4. 並用一個簡單的 if(editors != []) / if(viewers != []) 來處理如果有編輯、檢視者與加註者的情況。
  5. 同時,用 else 在沒有任何編輯、使用者時,則丟上空白的 Array([])。
  6. 最後再將它寫入 Google Sheet
function readFiles(){
  let folder = DriveApp.getFolderById(demo_drive_ID);
  let files = folder.getFiles();
  let files_arr = [["File Name","File ID", "Editors","Commenters","Viewers"]]
  while (files.hasNext()) {
    let file_info = []
    let file = files.next();
    let file_name = file.getName() 
    file_info.push(file.getName(),file.getId());
    let editors = file.getEditors();
    let viewers = file.getViewers();
    let editors_arr=[]
    let commenters_arr=[]
    let non_commenters_arr=[]
    if(editors != []){
        for(editor of editors){
          editors_arr.push(editor.getEmail())
        }
    }
    if(viewers != []){
        for(viewer of viewers){
          if(file.getAccess(viewer) == "COMMENT"){
            commenters_arr.push(viewer.getEmail())
          }else{
            non_commenters_arr.push(viewer.getEmail())
          }
        }
    }
    file_info.push(editors_arr)
    file_info.push(non_commenters_arr)
    file_info.push(commenters_arr)
    files_arr.push(file_info);
  };
  Logger.log(files_arr);
  writeData(files_arr);
}

跑起來長這樣——

好,那當我們會列出了以後,接著我們來看要怎麼設定。

Q3. 要怎麼設定(刪除與新增)Google Drive 中的檔案們的權限給不同人?

這邊就刪除和新增都講,一樣先用簡單的範例。假設我今天想要將檔案改成——

變更前權限狀態 變更後權限狀態
Spread Sheet 1 有一名編輯者 有一名檢視者
Spread Sheet 2 有一名檢視者 有一名加註者
Spread Sheet 3 有一名加註者 有一名編輯者

Step 5 刪除使用者權限

透過 removeEditor()removeViewer()removeCommenter() ,在 () 中放入使用者(或是使用者的 email)可以刪除使用者的權限。在這部步驟可以預期的是——

變更前權限狀態 變更後權限狀態
Spread Sheet 1 有一名編輯者 (沒有使用者)
Spread Sheet 2 有一名檢視者 (沒有使用者)
Spread Sheet 3 有一名加註者 (沒有使用者)
function readFileAndRemoveUser(){
  let folder = DriveApp.getFolderById(demo_drive_ID);
  let files = folder.getFiles();
  while (files.hasNext()) {
    let file = files.next();
    let file_name = file.getName();
    let editors = file.getEditors();
    let viewers = file.getViewers();
    for(editor of editors){
      file.removeEditor(editor)
      Logger.log('File ' +file_name +' removed editor: '+editor.getEmail());
    }
    for(viewer of viewers){
      if(file.getAccess(viewer) == "COMMENT"){
        file.removeCommenter(viewer)
        Logger.log('File ' +file_name +' removed commenter: '+viewer.getEmail());
      }else{
        file.removeViewer(viewer)
        Logger.log('File ' +file_name +' removed viewer: '+viewer.getEmail());
      }
    }
  };
};

好,來看看跑出來的結果。

Step 6 對列出使用者(email)設定特定權限

那接下來我們要新增「使用者」對檔案的權限,我會建議先參照今天的 Q2 把所有想處理的檔案名稱、ID 與目前的使用者狀況列出來先。如果要乾淨的處理,甚至可以參考 Q3 的 Step 5 先把所有的權限清理乾淨再來新增。

那新增的方式有三種,分別是 addEditor()addViewer()addCommenter()。我們來試著將前一份有 File Name 和 ID 的表單弄成我們要的順序。在這步驟預計會做的事是...

變更前權限狀態 變更後權限狀態
Spread Sheet 1 (沒有使用者) 有一名檢視者
Spread Sheet 2 (沒有使用者) 有一名加註者
Spread Sheet 3 (沒有使用者) 有一名編輯者

首先先取得 Google Sheet 裡面的資料,

function addUsers(){
  // Read Data from sheet
  let sheet = SpreadsheetApp.getActiveSheet();
  let range = sheet.getRange(3,1,3,5);
  let data_arr =  range.getValues();
  for (data of data_arr){
    let file_ID = data[1];
    let editors_mail_arr = data[2];
    let viewers_mail_arr = data[3];
    let commenters_mail_arr = data[4];
    let file = DriveApp.getFileById(file_ID);
    if(editors_mail_arr!=[]) file.addEditor(editors_mail_arr);
    if(viewers_mail_arr!=[]) file.addViewer(viewers_mail_arr);
    if(commenters_mail_arr!=[]) file.addCommenter(commenters_mail_arr);
  };
};

最後運作起來會長這樣——

如果不只新增一個使用者,那填寫方式是如圖,用小逗號隔開。

並將 file.addEditor(editors_mails_arr); 改成 file.addEditors([editors_mails_arr]); 也就是加上 s 並把括弧內包一層 Array []

那這邊示範新增多人的示範程式碼,把上方完整程式碼的三個 if 換成下列即可——

if(editors_mail_arr!=[]) file.addEditors([editors_mail_arr]);
if(viewers_mail_arr!=[]) file.addViewers([viewers_mail_arr]);
if(commenters_mail_arr!=[]) file.addCommenters([commenters_mail_arr]);

好,那今天我們總共學的,概括起來是這個表格。希望有幫助到大家。

編輯者 檢視者 加註者
讀取目前 getEditors() getViewers() (在 getViewers() 中再用 getAccess() 進行區分)
新增(單人) addEditor() addViewer() addCommenter()
新增(多人) addEditors() addViewers() addCommenters()
刪除 removeEditor() removeViewer() removeCommenter()

那目前對使用者進行操作目前是沒有 Quota 的限制。

延伸思考題

  1. 如果想要將 Google Drive 內的所有檔案抓出來,並關閉所有的使用權,請問要如何達到?
  2. 如果想要抓出四散在 Google Drive 內中 鐵人 開頭的檔案,並設定使用權限,請問如何達到?
  3. (進階題)要如何將將 Google Drive 內的檔案讀出,並更換擁有者(Owner)(提示:setOwner

好,那就完成了我們的 D10(撒花)。如果還有問題,透過留言之外,也可以到 Facebook Group,想開很久這次鐵人賽才真的開起來哈哈哈,歡迎來當 Founding Member。如果不想錯過可以訂閱按讚小鈴鐺(?),也歡迎留言跟我說你還想知道什麼做法/主題。我們明天見。


上一篇
D9 - 如何用 Google Apps Script 自動化對 Google Drive 的操作?(一)列出所有檔案 ID 與相關資訊
下一篇
D11 - 如何用 Apps Script 寄出客製化的表單並搜集分散在 Google Sheet 中的回應?(ㄧ)複製並客製你的 Google Form
系列文
整合 Google 服務的燃料——透過 Google Apps Script (GAS) 加速你的工作速度30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言